离线地图显示 (离线矢量地图)Sample详情 (离线瓦片地图)Sample详情

最后更新时间:2019年7月4日

离线地图显示方法

离线地图数据类型包括离线矢量地图和离线瓦片地图,两种地图加载显示的方式也略有不同:

加载地图有多种方法,不同的方法适用于不同的数据类型,具有不同的应用场景。离线矢量地图、离线瓦片地图显示的核心方法如下表所示,从表中可以观察到,它们具有三种相同的方法,另外各自具有一种独有的方法,开发者可根据数据类型、实际需求来确定采用哪种方法。

方法 接口 地图类型 使用场景
加载地图文档 loadFromFile / loadFromFileAsync 矢量 / 瓦片 最常用,适于地图文档中只有一个地图的情况,若有多个地图则默认加载第一个。
加载地图文档对应索引的地图 loadFromDocument / loadFromDocumentAsync 矢量 / 瓦片 适于加载有多个地图的地图文档,可控制加载某个地图。
通过地图文档获取Map setMap / setMapAsync 矢量 / 瓦片 适于加载地图之前需处理的情况,如删除部分图层、获取信息等。
通过数据库创建图层,从而构建Map setMap / setMapAsync 矢量 若获取到的数据只有“.mgdb”,无“.mapx”时,只能采用此方法。
基于ServerLayer实例化Map setMap / setMapAsync 瓦片 直接使用代加载瓦片地图,不用在桌面工具中配置地图文档。

一、加载地图文档

调用loadFromDocument / loadFromDocumentAsync方法加载地图文档,此方法是加载离线地图最常用、最简单的一种。前提是必须事先组织配置好mapx地图文档文件。

加载地图,采用MGSMapView作为地图容器,那么就首先需要引入下列头文件。

#import <MapGIS_Mobile_Map/mapview/MGSMapView.h>

可用代码方式构建MGSMapView控件,也可在StoryBoard故事板或xib中构建。构建完成后获取地图文档路径,调用loadFromDocument / loadFromDocumentAsync方法即可加载地图。核心代码如下:

#import "ShowDocVectorMap_ViewController.h"

#import <MapGIS_Mobile_Map/mapview/MGSMapView.h>

@interface ShowDocVectorMap_ViewController ()<MapViewDelegate>

//定义地图视图控件对象
@property (weak, nonatomic) IBOutlet MGSMapView *mapView;

@end

@implementation ShowDocVectorMap_ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //地图文档路径
    NSString *mapPath=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"/MapGIS Mobile 2D Sample/Map/MapShow/WuHan/WuHan.mapx"];
    
    //同步方法
    [_mapView loadFromFile:mapPath];
    
    //设置代理
    [_mapView setDelegate:self];
    //异步方法
    [_mapView loadFromFileAsync:offlineMapPath];
}

@end

加载地图,根据实际需求选择同步方法或者异步方法。如果采用异步方法加载地图,可以利用MGSMapView的代理回调方法判断地图的加载情况,使用方法如下。

(1)使ViewController遵守MapViewDelegate地图控件代理协议:

@interface ShowDocVectorMap_ViewController ()<MapViewDelegate>

(2)为地图视图设置代理:

//设置代理
[_mapView setDelegate:self];

(3)然后实现代理的地图加载回调函数:

//开始加载地图监听
-(void)willStartLoadingMapWithMapView:(MGSMapView *)mapView strDocPath:(NSString *)strDocPath{
    NSLog(@"开始加载地图");
}

//加载地图完成事件监听
-(void)didFinishLoadingMapWithMapView:(MGSMapView *)mapView strDocPath:(NSString *)strDocPath{
    NSLog(@"地图加载成功");
}

//加载地图失败事件监听
-(void)didFailLoadingMapWithMapView:(MGSMapView *)mapView strDocPath:(NSString *)strDocPath{
    NSLog(@"地图加载失败");
}

说明:缩放地图到某个范围或级别、添加覆盖物、地图要素查询编辑等地图操作,都需要在地图加载成功后才执行。

二、加载地图文档对应索引的地图

通过loadFromDocument / loadFromDocumentAsync来加载地图文档对应索引的地图,可以加载mapx地图文档中的指定地图,同样适用于离线矢量地图、离线瓦片地图。核心实现代码如下,在实现之前同样需要导入对应的头文件。

//定义地图视图控件、地图文档对象
@property (weak, nonatomic) IBOutlet MGSMapView *mapView;
@property (nonatomic,strong) MGSDocument *document;
//地图文档路径
NSString *mapPath=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"/MapGIS Mobile 2D Sample/Map/MapShow/WuHan/WuHan.mapx"];

_document=[[MGSDocument alloc] init];
//打开地图文档
[_document open:offlineMapPath];

//同步方法
[_mapView loadFromDocument:_document andIndex:0];

//异步方法
[_mapView loadFromDocumentAsync:_document andIndex:0 callback:^(BOOL success) {
    if (success) {
        //地图加载成功
    } else {
        //地图加载失败
    }
}];

说明:在异步方法的回调函数中可判断地图的加载情况。

三、通过地图文档获取Map

通过地图文档MGSDocument获取MGSMap,调用setMap / setMapAsync方法加载地图。同样可以加载地图文档中指定的地图。

//定义地图视图、地图、地图文档对象
@property (weak, nonatomic) IBOutlet MGSMapView *mapView;
@property (nonatomic,strong) MGSMap *map;
@property (nonatomic,strong) MGSDocument *document;
//地图文档路径
NSString *mapPath=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"/MapGIS Mobile 2D Sample/Map/MapShow/WuHan/WuHan.mapx"];

//创建文档对象
_document=[[MGSDocument alloc] init];
//打开地图文档
[_document open:mapPath];

//创建map,并获取地图文档中第一个地图
_map=[[MGSMap alloc] init];
_map=[[_document maps] getMapAtIndex:0];

//同步方法为地图视图设置地图对象
[_mapView setMap:_map];

//异步方法为地图视图设置地图对象
[_mapView setMapAsync:_map callback:^(BOOL success) {
    if (success) {
        //地图加载成功
    } else {
        //地图加载失败
    }
}];

代码说明:利用setMap或setMapAsync将地图MGSMap赋予给地图视图MGSMapView时,MGSMap对象需定义为成员变量,从而实现生命周期的正确管理。

四、通过数据库创建图层构建Map

通过通过数据库MGSDataBase获取数据,创建图层,从而构建MGSMap,然后调用setMap / setMapAsync方法加载地图。此方法只适用于离线矢量数据,针对获取的数据中只有.mgdb数据库,无.mapx地图文档时。

//定义地图视图、地图、数据库对象
@property (weak, nonatomic) IBOutlet MGSMapView *mapView;
@property (nonatomic,strong) MGSMap *map;
@property (nonatomic,strong) MGSDataBase *dataBase;
//地图文档路径
NSString *dbPath=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"/MapGIS Mobile 2D Sample/Map/MapShow/WuHan/武汉MKT.mgdb"];

//创建数据库对象
_dataBase=[[MGSDataBase alloc] init];
//打开数据库
[_dataBase open:offlineDataBasePath];

//创建地图对象
_map=[[MGSMap alloc] init];

if ([_dataBase hasOpened]) {
    //获取数据库中所有简单要素类的ID
    MGSIntList *intlist1=[_dataBase getXclseIDs:SFCls dsID:0];
    //遍历简单要素类
    for (int i=0; i<[intlist1 size]; i++) {
        //创建矢量图层
        MGSVectorLayer *vectorLayer=[[MGSVectorLayer alloc] initWithType:SFClsLayer];

        //根据id获取类信息
        MGSFClsInfo *fclsInfo=[_dataBase getXclsInfoWithType:SFCls clsID:[intlist1 getAtIndex:i]];

        //得到类信息,赋给vectorlayer
        [vectorLayer setUrl:[fclsInfo getURL]];
        [vectorLayer setName:[fclsInfo getName]];

        //为地图添加图层
        [_map append:vectorLayer];
    }

    //获取数据库中所有注记类的ID
    MGSIntList *intlist2=[_dataBase getXclseIDs:ACls dsID:0];
    //遍历注记类
    for (int i=0; i<[intlist2 size]; i++) {
        //创建矢量图层
        MGSVectorLayer *vectorLayer=[[MGSVectorLayer alloc] initWithType:AnnLayer];

        //根据id获取类信息
        MGSFClsInfo *fclsInfo=[_dataBase getXclsInfoWithType:ACls clsID:[intlist2 getAtIndex:i]];

        //得到类信息,赋给vectorlayer
        [vectorLayer setUrl:[fclsInfo getURL]];
        [vectorLayer setName:[fclsInfo getName]];

        //为地图添加图层
        [_map append:vectorLayer];
    }

    //为地图容器设置地图(同步方法)
    [_mapView setMap:_map];

    //为地图容器设置地图(异步方法)
    [_mapView setMapAsync:_map callback:^(BOOL success) {
        if (success) {
            //地图加载成功
        } else {
            //地图加载失败
        }
    }];
} else {
    //数据库打开失败
}

五、基于ServerLayer实例化Map

通过服务图层MGSServerLayer实例化MGSMap,然后调用setMap / setMapAsync方法加载地图。离线瓦片地图能够采用此方法,不适用于离线矢量地图。此方法加载离线瓦片数据不用将其组织为地图文档,直接加载.TDF格式的瓦片数据文件即可。

//定义地图视图、地图
@property (weak, nonatomic) IBOutlet MGSMapView *mapView;
@property (nonatomic,strong) MGSMap *map;
//获取本地瓦片地图路径
NSString *tilePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:@"/MapGIS Mobile 2D Sample/Map/MapShow/WorldMKTTile.TDF"];

//地图服务,根据MAPSERVER_TYPE_HDF类型创建
MGSMapServer* mapServer = [MGSServerLayer createMapServerByType:MAPSERVER_TYPE_HDF];
[mapServer setName:@"离线瓦片地图"];
[mapServer setUrl:tilePath];

//创建服务图层
MGSServerLayer *serverLayer=[[MGSServerLayer alloc] init];
[serverLayer setMapServer:mapServer];

//创建地图
_map=[[MGSMap alloc] init];
//为地图添加服务图层
[_map append:serverLayer];

//同步方法为地图容器设置地图
[_mapView setMap:_map];

//异步方法为地图容器设置地图
[_mapView setMapAsync:_map callback:^(BOOL success) {
    if (success) {
        //地图加载成功
    } else {
        //地图加载失败
    }
}];

显示效果如下所示:

离线矢量地图显示效果.jpg 离线瓦片地图显示效果.jpg